import {
  CommandDialog,
  type CommandDialogPlacement,
  BaseCommand,
  http,
  CSLineSegments,
  getQueryParam,
  QueryParamKeys,
} from '@amcax/base';
import { wsApi } from '../../../../server';
import { Input, Menu, Button, Modal, Spin } from 'antd';
import { useEffect, useState } from 'react';
import {
  AirFormDataLike,
  Forecast,
  cmdAirfoilAPI,
  getAirfoilVertexes,
} from '../cmd-airfoil/cmdAirfoilAPI';
import SubMenu from 'antd/lib/menu/SubMenu';
import { Vector3 } from 'three';
import { Renderer3D, RendererMgr } from '@amcax/renderer';
import { clearLocalListDatas } from '../../widgets/RightNavigation/panels/InputPanel';
import { clearAllModels } from '../cmd-clearScene';
import { ctx2, previewer, userEvents } from '../../../../module';

// 翼型
interface AirfoilCommandProps {
  title: string;
  onClose: () => void;
  placement: CommandDialogPlacement;
}

const documentId = getQueryParam<string>(QueryParamKeys.DOCUMENT_ID);

export const initAirfoil = async () => {
  const dxidJSON = await wsApi.getAppData(documentId + 'dxid');
  const dxid = JSON.parse(dxidJSON);
  const pointsPos = await getAirfoilVertexes();
  const { xMin, xMax } = pointsPos.reduce(
    (acc, point) => ({
      xMin: Math.min(acc.xMin, point.x),
      xMax: Math.max(acc.xMax, point.x),
    }),
    { xMin: Infinity, xMax: -Infinity },
  );
  const len = Number(xMax - xMin);
  const factor = 1 / len;
  const _points: [] = pointsPos.map((point: Vector3) => {
    return [point.x * factor, point.y * factor, point.z];
  });
  await wsApi.setParams(dxid, { points: _points });
  setTimeout(() => {
    ctx2.viewer.sceneSetup.fit2DView();
  }, 200);
};

function AirfoilOptimizeCommand({
  title,
  onClose,
  placement,
}: AirfoilCommandProps) {
  /**几何信息*/
  const [airFormData, setAirFormData] = useState<AirFormDataLike>({
    camber_max: 0.02,
    camber_max_pos: 0.3,
    thickness_max: 0.12,
    thickness_max_pos: 0.3,
    leading_radius_index: 8,
    lift_angle: 0,
    mach_number: 0.785,
    reynolds_number: 5e6,
  });
  /**评估结果*/
  const [forecast, setForecast] = useState<Forecast>({
    drag: 1000.0,
    lift: 2000.1,
  });
  /**编辑状态*/
  const [open, setOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [confirmLoading, setConfirmLoading] = useState(false);
  const [isFirstCreate, setIsFirstCreate] = useState(true);
  const [preview, setPreview] = useState(true);
  const [optimize, setOptimize] = useState(false);
  const [updating, setUpdating] = useState(false);
  const [dxid, setDxid] = useState(null);

  const edgeGroup = ctx2.cadScene.edgeGroup;

  useEffect(() => {
    // 启动预览
    // startAction();
    // 优化按钮
    if (edgeGroup.children.length > 0) {
      const edge = edgeGroup.children[0] as CSLineSegments;
      setDxid(edge.modelDxid);
      updateInfo();
      setIsFirstCreate(false);
    }

    // 初始化翼型尺寸，此命令下翼型尺寸只允许为 1mm
    initAirfoil();
  }, []);

  const handleExecute = async () => {
    setLoading(true);
    await applyOptimize();
    clearLocalListDatas();
    setLoading(false);
    onClose();
  };

  const handlePreview = async () => {
    setLoading(true);
    await optimizePreview();
    setLoading(false);
    setOptimize(true);
  };

  const handleClose = () => {
    cancel();
    onClose();
  };

  /**同步表单参数 */
  const updateInfo = async () => {
    getData().then((data) => {
      const params = JSON.parse(data);
      const airformParams = {
        camber_max: params.camber_max,
        camber_max_pos: params.camber_max_pos,
        thickness_max: params.thickness_max,
        thickness_max_pos: params.thickness_max_pos,
        leading_radius_index: params.leading_radius_index,
        lift_angle: params.lift_angle,
        mach_number: params.mach_number,
        reynolds_number: params.reynolds_number,
      };
      setAirFormData(airformParams);
      const forecastParams = {
        drag: params.drag,
        lift: params.lift,
      };
      setForecast(forecastParams);
    });
  };

  /**nextCore储存数据 */
  const saveData = async () => {
    const params = {
      camber_max: airFormData.camber_max,
      camber_max_pos: airFormData.camber_max_pos,
      thickness_max: airFormData.thickness_max,
      thickness_max_pos: airFormData.thickness_max_pos,
      leading_radius_index: airFormData.leading_radius_index,
      lift_angle: airFormData.lift_angle,
      mach_number: airFormData.mach_number,
      reynolds_number: airFormData.reynolds_number,
      drag: forecast.drag,
      lift: forecast.lift,
    };
    const data = JSON.stringify(params);
    await wsApi.saveAppData(documentId + 'params', data);
  };
  /**nextCore获取数据 */
  const getData = async () => {
    return await wsApi.getAppData(documentId + 'params');
  };

  /**修改表单参数 */
  const handleAirFormDataChange = (minValue, maxValue) => (event) => {
    let { name, value, type } = event.target;
    if (isNaN(value)) {
      return;
    }
    setAirFormData((prevState) => ({
      ...prevState,
      [name]: value,
    }));
    // 更新按钮状态
    setPreview(true);
    setOptimize(false);
  };

  /**校验表单参数 */
  const checkAirformData = (minValue, maxValue) => (event) => {
    let { name, value, type } = event.target;
    if (type === 'number') value = Number(value);
    if (isNaN(value)) {
      return;
    }
    if (value < minValue) {
      value = minValue;
    } else if (value > maxValue) {
      value = maxValue;
    }
    setAirFormData((prevState) => ({
      ...prevState,
      [name]: value,
    }));
    // 更新按钮状态
    setPreview(true);
    setOptimize(false);
  };

  /**
   * 生成翼型
   * 请求接口 获取翼型数据 进入生成命令
   */
  const executeCmdAirfoil = async (editChange = false) => {
    const paramData = await new Promise<Array<Vector3>>(async (resolve) => {
      // setTimeout(async () => {
      const params = {
        camber_max: airFormData.camber_max,
        camber_max_pos: airFormData.camber_max_pos,
        thickness_max: airFormData.thickness_max,
        thickness_max_pos: airFormData.thickness_max_pos,
        leading_radius_index: airFormData.leading_radius_index,
      };
      // 翼型生成
      const generateAddr = `/airfoil/v1/${documentId}/generate`;
      await http.post(generateAddr, params).then((res) => {
        const jsonPoints = JSON.stringify(res.data.data);
        const pointsPos = JSON.parse(jsonPoints);
        const points3d = pointsPos.map((item) => {
          return new Vector3(item.x, item.y, 0);
        });
        resolve(points3d);
      });
    });
    const data = {
      params: paramData,
      dxid: dxid,
    };
    if (isFirstCreate) {
      await cmdAirfoilAPI.invoke(data).then((res) => {
        setDxid(res);
      });
    } else if (editChange) {
      data.dxid = null;
      await cmdAirfoilAPI.invoke(data).then((res) => {
        setDxid(res);
      });
      finishDraw();
      ctx2.viewer.sceneSetup.fit2DView();
    } else {
      cmdAirfoilAPI.invoke(data);
    }
    saveData();
    onClose();
  };

  /**
   * 翼型评估
   */
  const evaluateAirfoil = async () => {
    const evaluateAddr = `/airfoil/v1/${documentId}/evaluate`;
    const datas = await http.post(evaluateAddr, airFormData).then((res) => {
      const jsonForecast = JSON.stringify(res.data.evaluation);
      const forecast = JSON.parse(jsonForecast);
      setForecast(forecast);
      const jsonAirform = JSON.stringify(res.data.opt_param);
      const airform = JSON.parse(jsonAirform);
      const airformParams = {
        camber_max: airform.camber_max,
        camber_max_pos: airform.camber_max_pos,
        thickness_max: airform.thickness_max,
        thickness_max_pos: airform.thickness_max_pos,
        leading_radius_index: airform.leading_radius_index,
        lift_angle: airFormData.lift_angle,
        mach_number: airFormData.mach_number,
        reynolds_number: airFormData.reynolds_number,
      };
      setAirFormData(airformParams);
      return airformParams;
    });
    return datas;
  };

  /**
   * 获取优化数据
   */
  const getOptimizeData = async () => {
    const data = await evaluateAirfoil();
    const optimizeData = await new Promise<Array<Vector3>>(async (resolve) => {
      const generateAddr = `/airfoil/v1/${documentId}/generate`;
      await http.post(generateAddr, data).then((res) => {
        const jsonPoints = JSON.stringify(res.data.data);
        const pointsPos = JSON.parse(jsonPoints);
        const points3d = pointsPos.map((item) => {
          return new Vector3(item.x, item.y, 0);
        });
        resolve(points3d);
      });
    });
    return optimizeData;
  };

  /**
   * 翼型优化预览
   */
  const optimizePreview = async () => {
    // 按钮状态更新
    setPreview(false);
    setUpdating(true);
    const optimizeData = await getOptimizeData();
    setUpdating(false);
    setIsFirstCreate(false);
    // 预览
    previewAirfoil(optimizeData);
  };

  /**
   * 开始预览
   */
  const previewAirfoil = async (data) => {
    const _points = data.map((point: Vector3) => {
      return [point.x, point.y, point.z];
    });
    // await wsApi
    //   .getEngine()
    //   .execCmd({
    //     c: 'ExecuteTransaction',
    //     type: 'Bspline',
    //     a: { mode: 'Approx', points: _points },
    //   })
    //   .then((res) => {
    //     const models = getPreviewData(res);
    //     if (models?.length > 0) {
    //       previewer.clear();
    //       previewer.preview(models);
    //     }
    //   });
    const res = await execCmd(_points, true);
    const models = getPreviewData(res);
    if (models?.length > 0) {
      previewer.clear();
      previewer.preview(models);
    }
  };

  const execCmd = async (_points, isPreview=false) => {
    const params = {
      c: 'CreateCurve',
      type: 'Bspline',
      a: { mode: 'Approx', points: _points },
      p: isPreview
    }
    return await wsApi.getEngine().execCmd(params);
  };

  // const startAction = async () => {
  //   await wsApi.getEngine().execCmd({
  //     c: 'StartTransaction',
  //     n: 'CreateCurve',
  //   });
  // };

  // const abortAction = async () => {
  //   await wsApi.getEngine().execCmd({
  //     c: 'AbortTransaction',
  //   });
  // };

  // const endAction = async () => {
  //   await wsApi.getEngine().execCmd({
  //     c: 'EndTransaction',
  //   });
  // };

  const getPreviewData = (data) => {
    return RendererMgr.getRender<Renderer3D>('3d').parsePreviewModels(data);
  };

  /**
   * 应用优化
   */
  const applyOptimize = async () => {
    await saveData();
    // await abortAction();
    clearPreview();
    await updateAirfoil();
    onClose();
  };

  const updateAirfoil = async () => {
    const dxidJSON = await wsApi.getAppData(documentId + 'dxid');
    const dxid = JSON.parse(dxidJSON);
    const data = await getOptimizeData();
    const _points = data.map((point: Vector3) => {
      return [point.x, point.y, point.z];
    });
    await wsApi.setParams(dxid, { points: _points });
  };

  const finishDraw = async () => {
    userEvents.emit('CMD_MGR_EXECUTED', false);
  };

  /**
   * 取消
   */
  const cancel = async () => {
    // await abortAction();
    clearPreview();
  };

  /**
   * 清除预览
   */
  const clearPreview = () => {
    previewer.clear();
  };

  /**
   * 编辑后 更新翼型提示框
   */
  const handleOk = async () => {
    setConfirmLoading(true);
    await clearAllModels();
    await executeCmdAirfoil(true);
    setConfirmLoading(false);
    clearLocalListDatas();
    onClose();
  };

  const handleCancel = () => {
    setOpen(false);
    updateInfo();
  };

  return (
    <CommandDialog
      title={title}
      onClose={handleClose}
      placement={placement}>
      <div className='box'>
        <Menu
          defaultSelectedKeys={['999']}
          defaultOpenKeys={['sub1', 'sub2', 'sub3']}
          mode='inline'
          className='meun-panel'>
          <SubMenu
            key='sub1'
            title={
              <span className='menu-title'>
                几何信息
                {updating && (
                  <span
                    className='menu-title'
                    style={{ color: '#1677ff' }}>
                    （更新中..）
                  </span>
                )}
              </span>
            }
            className='meun-panel1'>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>前缘半径指数(R)</div>
              <div className='input1'>
                <Input
                  name='leading_radius_index'
                  type='number'
                  min='0.8'
                  max='8.0'
                  step='0.1'
                  suffix={updating ? <Spin size='small' /> : null}
                  disabled={true}
                  value={airFormData.leading_radius_index}
                  style={{ borderRadius: '10px', pointerEvents: 'auto' }}
                  onClick={(e) => {
                    e.stopPropagation();
                  }}
                />
              </div>
            </Menu.Item>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>最大厚度(T)</div>
              <div className='input1'>
                <Input
                  name='thickness_max'
                  type='number'
                  min='0.04'
                  max='0.4'
                  step='0.01'
                  suffix={updating ? <Spin size='small' /> : null}
                  disabled={true}
                  value={airFormData.thickness_max}
                  style={{ borderRadius: '10px', pointerEvents: 'auto' }}
                  onClick={(e) => {
                    e.stopPropagation();
                  }}
                />
              </div>
            </Menu.Item>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>最大厚度位置(Xt)</div>
              <div className='input1'>
                <Input
                  name='thickness_max_pos'
                  type='number'
                  min='0.2'
                  max='0.6'
                  step='0.1'
                  suffix={updating ? <Spin size='small' /> : null}
                  disabled={true}
                  value={airFormData.thickness_max_pos}
                  style={{ borderRadius: '10px', pointerEvents: 'auto' }}
                  onClick={(e) => {
                    e.stopPropagation();
                  }}
                />
              </div>
            </Menu.Item>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>最大弯度(F)</div>
              <div className='input1'>
                <Input
                  name='camber_max'
                  type='number'
                  min='0'
                  max='0.1'
                  step='0.01'
                  suffix={updating ? <Spin size='small' /> : null}
                  disabled={true}
                  value={airFormData.camber_max}
                  style={{ borderRadius: '10px', pointerEvents: 'auto' }}
                  onClick={(e) => {
                    e.stopPropagation();
                  }}
                />
              </div>
            </Menu.Item>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>最大弯度位置(Xf)</div>
              <div className='input1'>
                <Input
                  name='camber_max_pos'
                  type='number'
                  min='0.1'
                  max='0.9'
                  step='0.1'
                  suffix={updating ? <Spin size='small' /> : null}
                  disabled={true}
                  value={airFormData.camber_max_pos}
                  style={{ borderRadius: '10px', pointerEvents: 'auto' }}
                  onClick={(e) => {
                    e.stopPropagation();
                  }}
                />
              </div>
            </Menu.Item>
          </SubMenu>
          <SubMenu
            key='sub2'
            title={<span className='menu-title'>翼型评估</span>}
            className='meun-panel'>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>攻角</div>
              <div className='input1'>
                <Input
                  name='lift_angle'
                  type='number'
                  min='-5'
                  max='10'
                  step='1'
                  value={airFormData.lift_angle}
                  style={{ borderRadius: '10px', pointerEvents: 'auto' }}
                  suffix={<span style={{ color: '0xdadcdf' }}>度</span>}
                  onChange={handleAirFormDataChange(-5, 10)}
                  onBlur={checkAirformData(-5, 10)}
                  onClick={(e) => {
                    e.stopPropagation();
                  }}
                />
              </div>
            </Menu.Item>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>马赫数</div>
              <div className='input1'>
                <div style={{ color: 'black' }}>
                  {airFormData.mach_number?.toExponential(2)}
                </div>
              </div>
            </Menu.Item>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>雷诺数</div>
              <div className='input1'>
                <div style={{ color: 'black' }}>
                  {airFormData.reynolds_number?.toExponential(2)}
                </div>
              </div>
            </Menu.Item>
          </SubMenu>
          <SubMenu
            key='sub3'
            title={
              <span className='menu-title'>
                评估结果
                {updating && (
                  <span
                    className='menu-title'
                    style={{ color: '#1677ff' }}>
                    （更新中..）
                  </span>
                )}
              </span>
            }
            className='meun-panel1'>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>阻力系数</div>
              <div className='input1'>
                {!isFirstCreate && (
                  <div style={{ color: 'black' }}>
                    {forecast.drag?.toExponential(6)}
                  </div>
                )}
              </div>
            </Menu.Item>
            <Menu.Item
              className='menu-child'
              style={{ paddingLeft: '24px' }}>
              <div className='menu-child1'>升力系数</div>
              <div className='input1'>
                {!isFirstCreate && (
                  <div style={{ color: 'black' }}>
                    {forecast.lift?.toExponential(6)}
                  </div>
                )}
              </div>
            </Menu.Item>
          </SubMenu>
          <div
            style={{
              display: 'flex',
              paddingTop: '10px',
              paddingBottom: '10px',
              paddingRight: '4px',
              justifyContent: 'right',
            }}>
            <div style={{ paddingLeft: '0px', marginRight: '8px' }}>
              <Button
                style={{ borderRadius: '5px' }}
                onClick={handleClose}>
                {'取消'}
              </Button>
            </div>
            <div style={{ paddingLeft: '0px', marginRight: '8px' }}>
              <Button
                type='primary'
                style={{ borderRadius: '5px' }}
                onClick={handlePreview}
                disabled={!preview}>
                {'预览'}
              </Button>
            </div>
            <div style={{ paddingRight: '0px' }}>
              <Button
                type='primary'
                style={{ borderRadius: '5px' }}
                onClick={handleExecute}
                disabled={!optimize}>
                {'应用'}
              </Button>
            </div>
          </div>
        </Menu>
      </div>
      <Modal
        title='修改提示'
        open={open}
        onCancel={handleCancel}
        onOk={handleOk}
        confirmLoading={confirmLoading}
        okText='继续'
        cancelText='取消'
        style={{ borderRadius: '10px' }}>
        <p>您已进行数据编辑，重新生成翼型将清除之前数据，是否继续？</p>
      </Modal>
      <Modal
        open={loading}
        footer={null}
        closable={false}
        centered
        className='transparent-modal'>
        <div style={{ textAlign: 'center', padding: '20px' }}>
          <Spin
            tip='Loading...'
            spinning={loading}
            className='custom-spin'
          />
        </div>
      </Modal>
    </CommandDialog>
  );
}

export const cmdAirfoilOptimize: BaseCommand = {
  id: 'CmdAirfoilOptimize',
  label: '翼型优化',
  icon: 'commands/airfoil/optimize-airfoil',
  create: (label: string, onClose: () => void) => (
    <AirfoilOptimizeCommand
      title={'翼型优化'}
      onClose={onClose}
      placement='topLeft'
    />
  ),
  initialDisabled: true,
  subscribeDisabled: (setDisabled: (disabled: boolean) => void) => {
    const listener = (empty: boolean) => {
      setDisabled(empty);
    };
    const imported = (bool: boolean) => {
      setDisabled(bool);
    };
    userEvents.on('sceneEmpty', listener);
    userEvents.on('importAirfoil', imported);
    return () => {
      userEvents.off('sceneEmpty', listener);
      userEvents.off('importAirfoil', imported);
    };
  },
};
